ramXpos = {0, 0}
flagLeftClick = {}

-- default options
local guiOptBox = false
local guiBox = true
local guiHitBox = true
local guiEnemyBox = true
local guiEnemyHitBox = true
local guiGrid = false

option = {
    guiOptBox,
    guiBox,
    guiHitBox,
    guiEnemyBox,
    guiEnemyHitBox,
    guiGrid,
}

-- display rerecording count
function showRrcCount()
    local movieRrcCount = movie.rerecordcount()
    local guiRrcBoxPos = {158, 2}
    local guiRrcBoxScale = {80, 10}
    local guiRrcBoxColor = "#00000060"
    
    gui.box(guiRrcBoxPos[1], guiRrcBoxPos[2],
            guiRrcBoxPos[1] + guiRrcBoxScale[1],
            guiRrcBoxPos[2] + guiRrcBoxScale[2], guiRrcBoxColor, guiRrcBoxColor)
    gui.registerbefore.text(guiRrcBoxPos[1] + 3, guiRrcBoxPos[2] + 2,
             string.format(("RerecCount: %6s"), movieRrcCount))
end

-- display (no movie)
function showNoMovie()
    local guiNoMovieBoxPos = {158, 2}
    local guiNoMovieBoxScale = {80, 10}
    local guiNoMovieBoxColor = "#FF0000FF"

    gui.box(guiNoMovieBoxPos[1], guiNoMovieBoxPos[2],
            guiNoMovieBoxPos[1] + guiNoMovieBoxScale[1],
            guiNoMovieBoxPos[2] + guiNoMovieBoxScale[2], guiNoMovieBoxColor)
    gui.text(guiNoMovieBoxPos[1] + 24, guiNoMovieBoxPos[2] + 2, "(no movie)")
end

-- display Klonoa's coordinates and velocity
function showBox()
    local ramXspeed = memory.readword(0x03005238)
    local ramYspeed = memory.readwordsigned(0x03005248)
    local ramUnCtrl = memory.readbyte(0x03005253)
    local diffXpos = (ramXpos[1] - ramXpos[2])
    
    local guiBoxPos = {ramXpos[1] - ramCameraXpos - 28 , ramYpos - ramCameraYpos}
    local guiBoxScale = {54, 18}
    local guiBoxColor = "#00008060"
    
    if option[2] then
        gui.box(guiBoxPos[1], guiBoxPos[2], guiBoxPos[1] + guiBoxScale[1], 
                guiBoxPos[2] + guiBoxScale[2], guiBoxColor, guiBoxColor)
        gui.text(guiBoxPos[1] + 3, guiBoxPos[2] + 2, 
                 string.format("(%4x, %4x)",  ramXpos[1], ramYpos))
        if ramXspeed == 0 then
            gui.text(guiBoxPos[1] + 3, guiBoxPos[2] + 10, 
                    string.format("(%4s, %4s)", diffXpos, ramYspeed))
        else
            gui.text(guiBoxPos[1] + 3, guiBoxPos[2] + 10, 
                    string.format("(%4s, %4s)", ramXspeed, ramYspeed))
        end
    end
    return guiBoxPos
end

-- display Klonoa's hitbox (insufficiency)
function showHitBox()
    local guiHitBoxPos = {ramXpos[1] - ramCameraXpos - 0xB, 
                           ramYpos - ramCameraYpos - 0x18}
    local guiHitBoxColor = {"#A0A0A060", "#00008040"}

    gui.drawbox(guiHitBoxPos[1], guiHitBoxPos[2], 
                guiHitBoxPos[1] + 0x16, guiHitBoxPos[2] + 0x18, guiHitBoxColor[1])
    gui.box(guiHitBoxPos[1] + 7, guiHitBoxPos[2] + 7, 
                guiHitBoxPos[1] + 16, guiHitBoxPos[2] + 18, guiHitBoxColor[2])
end

-- display Klonoa's uncontrollable timer
function showUnCtrlTimer(guiBoxPos)
    gui.text(guiBoxPos[1] + 24, guiBoxPos[2] - 32, 
             string.format("%2d", ramUnCtrl))
end
-- display enemies' coordinates
function showEnemyBox(guiEnemyBoxXpos, guiEnemyBoxYpos, ramEnemyXpos, ramEnemyYpos)
    local guiEnemyBoxScale = {54, 9}
    local guiEnemyBoxColor = "#80000060"
    if option[4] then
        gui.box(guiEnemyBoxXpos, guiEnemyBoxYpos, guiEnemyBoxXpos + guiEnemyBoxScale[1],
                guiEnemyBoxYpos + guiEnemyBoxScale[2], guiEnemyBoxColor, guiEnemyBoxColor)
        gui.text(guiEnemyBoxXpos + 3 , guiEnemyBoxYpos + 2,
                 string.format("(%4x, %4x)", ramEnemyXpos, ramEnemyYpos))
    end
end

-- display enemies' hitbox (insufficiency)
function showEnemyHitBox(i, ramEnemyXpos, ramEnemyYpos)
    local guiEnemyHitBoxXpos = {}
    local guiEnemyHitBoxYpos = {}
    local guiEnemyHitBoxColor = "#80000080"
    if option[5] then
        guiEnemyHitBoxXpos[i] = ramEnemyXpos - ramCameraXpos - 4
        guiEnemyHitBoxYpos[i] = ramEnemyYpos - ramCameraYpos - 17

        gui.box(guiEnemyHitBoxXpos[i], guiEnemyHitBoxYpos[i], 
                guiEnemyHitBoxXpos[i] + 9, guiEnemyHitBoxYpos[i] + 12, 
                guiEnemyHitBoxColor)
    end
end

-- display boomie's sub-timer
function showSubBombTimer(ramSubBombTimer, guiEnemyBoxXpos, guiEnemyBoxYpos)
    gui.text(guiEnemyBoxXpos + 35, guiEnemyBoxYpos - 7, 
             string.format(".%2s", ramSubBombTimer))
end

-- display grids (insufficiency)
function showGrid()
    local guiGridXlinePos = {}
    local guiGridYlinePos = {}
    local guiGridLineColor = "#00000020"

    for i = 1, 12, 1 do
        guiGridXlinePos[i] = 0x18 * ( i - 1 ) - ramCameraYpos % 0x18
        guiGridYlinePos[i] = 0x18 * ( i - 1 ) - ramCameraXpos % 0x18
        gui.drawline(0, guiGridXlinePos[i], 240, guiGridXlinePos[i], 
                     guiGridLineColor)
        gui.drawline(guiGridYlinePos[i], 0, guiGridYlinePos[i], 160, 
                     guiGridLineColor)
    end
end

-- display box of options
function guiOptBox()
    local guiOptBoxPos = {10, 10}
    local guiOptBoxScale = {12, 100}
    local guiOptBoxColor = "#FFFFFF40"
    local guiOptButtonXpos = {}
    local guiOptButtonYpos = {}
    local guiOptButtonScale = {10, 10}
    local guiOptButtonOnColor = "#FF8040A0"
    local guiOptButtonOffColor = "#FFFFFF60"

    if option[1] then
        gui.box(guiOptBoxPos[1], guiOptBoxPos[2], guiOptBoxPos[1] + guiOptBoxScale[1],
                guiOptBoxPos[2] + guiOptBoxScale[2], guiOptBoxColor, guiOptBoxColor)

        for i = 1, 6, 1 do
            guiOptButtonXpos[i] = guiOptBoxPos[1] + 1
            guiOptButtonYpos[i] = guiOptBoxPos[2] + 12 * ( i - 1 ) + 1

            if flagLeftClick[3] and
            guiOptButtonXpos[i] + guiOptButtonScale[1] > emuInput.xmouse and
            emuInput.xmouse > guiOptButtonXpos[i] and
            guiOptButtonYpos[i] + guiOptButtonScale[2] > emuInput.ymouse and
            emuInput.ymouse > guiOptButtonYpos[i] then
                changeOnOff(i)
            end

            if option[i] then
                gui.box(guiOptButtonXpos[i], guiOptButtonYpos[i],
                        guiOptButtonXpos[i] + guiOptButtonScale[1],
                        guiOptButtonYpos[i] + guiOptButtonScale[2],
                        guiOptButtonOnColor, guiOptButtonOnColor)
            else
                gui.box(guiOptButtonXpos[i], guiOptButtonYpos[i],
                        guiOptButtonXpos[i] + guiOptButtonScale[1],
                        guiOptButtonYpos[i] + guiOptButtonScale[2],
                        guiOptButtonOffColor, guiOptButtonOffColor)
            end
        end
    else
        gui.box(guiOptBoxPos[1], guiOptBoxPos[2], guiOptBoxPos[1] + 12, guiOptBoxPos[2] + 12,
                guiOptBoxColor, guiOptBoxColor)
        if flagLeftClick[3] and
        guiOptBoxPos[1] + 12 > emuInput.xmouse and
        emuInput.xmouse > guiOptBoxPos[1] and
        guiOptBoxPos[2] + 12 > emuInput.ymouse and
        emuInput.ymouse > guiOptBoxPos[2] then
            changeOnOff(1)
        end
    end
end

function changeOnOff(j)
    if option[j] then
        option[j] = false
    else
        option[j] = true
    end
end
--[beginning main routine]--
emu.registerbefore(function()
    ramXpos[1] = memory.readword(0x03002920)
    ramYpos = memory.readword(0x03002922)
    ramCameraXpos = memory.readword(0x03003470)
    ramCameraYpos = memory.readword(0x03003472)
    ramUnCtrl = memory.readbyte(0x03005253)
    emuInput = input.get()
    flagLeftClick[1] = emuInput.leftclick

    if option[3] then
        showHitBox()
    end

    for i = 1, 20, 1 do
        local ramEnemyXpos = {}
        local ramEnemyYpos = {}
        local ramSubBombTimer = {}
        local guiEnemyBoxXpos = {}
        local guiEnemyBoxYpos = {}
        ramEnemyXpos[i] = memory.readword(0x03002A1C + 0xE * ( i - 1 ))
        ramEnemyYpos[i] = memory.readword(0x03002A1E + 0xE * ( i - 1 ))
        ramSubBombTimer[i] = memory.readbyte(0x03002A25 + 0xE * ( i - 1 ))

        guiEnemyBoxXpos[i] = ramEnemyXpos[i] - ramCameraXpos  - 30
        guiEnemyBoxYpos[i] = ramEnemyYpos[i] - ramCameraYpos
        -- gui.text(10,10*i,string.format(("%4s,%4s"),guiEnemyBoxXpos[i], guiEnemyBoxYpos[i]))
        if i == 1 or i >= 4 then
            showEnemyBox(guiEnemyBoxXpos[i], guiEnemyBoxYpos[i],
                         ramEnemyXpos[i], ramEnemyYpos[i])
            if guiEnemyHitBox then
                showEnemyHitBox(i, ramEnemyXpos[i], ramEnemyYpos[i])
            end
            if ramSubBombTimer[i] >= 3 then
                showSubBombTimer(ramSubBombTimer[i], guiEnemyBoxXpos[i], guiEnemyBoxYpos[i])
            end
        end
    end

    if option[6] then
        showGrid(ramCameraXpos, ramCameraYpos)
    end

    if movie.recording() or movie.playing() then
        showRrcCount()
    else
        showNoMovie()
    end

    local guiBoxPos = showBox()

    if ramUnCtrl > 0 then
        showUnCtrlTimer(guiBoxPos)
    end
    
    if not flagLeftClick[1] and flagLeftClick[2] then
        flagLeftClick[3] = true
    else
        flagLeftClick[3] = false
    end

    guiOptBox()
end)

vba.registerafter(function()
    flagLeftClick[2] = flagLeftClick[1]
    ramXpos[2] = ramXpos[1]
end)
